package com.hx.vending.mqtt;

import com.hx.vending.bean.*;
import com.hx.vending.dao.*;
import com.hx.vending.util.BigDecimalUtils;
import com.hx.vending.util.PubMsg;
import com.hx.vending.util.PushUtils;
import com.hx.vending.util.ToolUtil;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.List;

/**
 * Created by Administrator on 2018/12/16.
 * 发送mqtt
 */
public class RunnerSendMqtt implements Runnable {

    //获取logger实例
    private static Logger logger = Logger.getLogger(RunnerSendMqtt.class);
    private ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-mybatis.xml");
    private OrderBuyMapper orderBuyMapper = ioc.getBean(OrderBuyMapper.class);
    private EquipmentMapper equipmentMapper = ioc.getBean(EquipmentMapper.class);
    private OnlineOrderMapper onlineOrderMapper = ioc.getBean(OnlineOrderMapper.class);
    private OrderFailMapper orderFailMapper = ioc.getBean(OrderFailMapper.class);
    private UserMapper userMapper = ioc.getBean(UserMapper.class);
    private DictMapper dictMapper = ioc.getBean(DictMapper.class);
    private TrailsMapper trailsMapper = ioc.getBean(TrailsMapper.class);

    //缓存对象
    private RedisTemplate<String, String> redisTemplate;
    //线程对象
    private Thread thread;
    //线程名称
    private String threadName;
    //发送的mqtt消息(设备id加出货信息,没有随机数)(出货消息只发送了设备id)
    private String message;
    //要发送的mqtt主题
    private String theme;
    //redis的key
    private String redisKey;
    //线上订单id
    private Integer onlineOrderId;
    //货到测试集合信息
    private List<Trails> trailsList;


    @Override
    public void run() {
        String redisMessage = null;//应答

        String [] trailsMs = message.split(",");

        try {
            if (theme.equals("Delivery")) {//出货主题
                String redisMessageSuccess = null;//出货成功应答
                //用于保存出货成功的商品消耗的
                String stockMessage = trailsMs[0];

                //出货的货道信息
                OrderBuy orderBuy = new OrderBuy();
                orderBuy.setOrderBuyParentId(onlineOrderId);
                List<OrderBuy> orderBuys = this.orderBuyMapper.selectByExampleSelective(orderBuy);

                //一个商品发送一次消息
                for (OrderBuy forOrderBuy: orderBuys) {
                    //查询货道
                    Trails trails = new Trails();
                    trails.setTrailsId(forOrderBuy.getOrderBuyTrailsId());
                    Trails selectTrails = this.trailsMapper.selectByPrimaryKeySelective(trails);
                    //判断该货道是否故障，故障直接跳过
                    if (ToolUtil.isNotEmpty(selectTrails)) {
                        if (selectTrails.getTrailsAlarm()!=0) {
                            forOrderBuy.setOrderBuyRefund(0);//未退款
                            forOrderBuy.setOrderBuyState(2);//出货失败
                            this.orderBuyMapper.updateByPrimaryKeySelective(forOrderBuy);
                            continue;
                        }
                    }

                    String fourNumber = ToolUtil.getRandom();//随机数(每次出商品应答失败后不能更换随机数)

                    A:for (int j = 0; j < 8; j++) {//每个商品无应答最多发送八次
                        logger.error("发送mqtt消息: 主题:("+theme+") 消息:("+message+") 第" + (j+1) + "次");

                        ////////////////////////////////发送消息//////////////////////////////////
                        String trailsType = "";
                        String shipmentNumber = "1";
                        if (ToolUtil.isNotEmpty(forOrderBuy.getOrderBuyTrailsType())) {
                            Dict dict = new Dict();
                            dict.setId(forOrderBuy.getOrderBuyTrailsType());
                            Dict selectDice = this.dictMapper.selectByPrimaryKeySelective(dict);
                            if (selectDice.getNum() == 1) {
                                trailsType = "A";//弹簧
                            }else if (selectDice.getNum() == 3) {
                                trailsType = "B";//电子锁
                            }else if (selectDice.getNum() == 2) {
                                trailsType = "C";//履带
                                shipmentNumber = selectTrails.getTrailsTrackTime().toString();
                            }
                        }
                        String sendMsg = trailsMs[0] + "," + fourNumber + "," + forOrderBuy.getOrderBuyPosition() + ","+ shipmentNumber +"," + trailsType + "," + selectTrails.getTrailsCaseId();
                        PubMsg.publish(sendMsg, "Delivery/" + trailsMs[0]);

                        /////////////////////////////////接收消息//////////////////////////////////
                        for (int getMsg = 0; getMsg < 5; getMsg++) {
                            Thread.sleep(1000);
                            //获取缓存数据
                            redisMessage = redisTemplate.boundValueOps(redisKey).get();
                            if (ToolUtil.isNotEmpty(redisMessage)) {
                                B:for (int getSuccess = 0; getSuccess < 40; getSuccess++) {
                                    Thread.sleep(1000);
                                    ////////////////////////////接收到故障消息//////////////////////////////
                                    String Alarm = redisTemplate.boundValueOps("Alarm-" + trailsMs[0]).get();

                                    //如果出货的时候收到故障主题就跳过这个货道，并修改货道出货信息
                                    if (ToolUtil.isNotEmpty(Alarm)) {
                                        //判断出货状态
                                        String[] alarms = Alarm.split(",");
                                        if (alarms[2].equals("3") || alarms[2].equals("4")) {
                                            forOrderBuy.setOrderBuyState(1);//已出货,故障码12567不减库存,34减库存
                                            stockMessage = stockMessage + "," + forOrderBuy.getOrderBuyPosition() + ",1," + forOrderBuy.getOrderBuyCaseId();
                                        }else {
                                            forOrderBuy.setOrderBuyState(2);//出货失败
                                        }

                                        redisTemplate.delete("Alarm-" + trailsMs[0]);
                                        break A;
                                    }
                                    ////////////////////////////接收到出货成功消息//////////////////////////////
                                    redisMessageSuccess = redisTemplate.boundValueOps("DeliverySuccess-" + trailsMs[0]).get();
                                    if (ToolUtil.isNotEmpty(redisMessageSuccess)) {
                                        redisTemplate.delete("DeliverySuccess-" + trailsMs[0]);
                                        String[] successMsg = redisMessageSuccess.split(",");
                                        if (!successMsg[2].equals(forOrderBuy.getOrderBuyPosition())) {
                                            continue A;
                                        }
                                        break B;
                                    }
                                }
                            }

                            logger.error("接收缓存的消息:" + redisMessage + "\n" + redisMessageSuccess);

                            //////////////////////////////出货成功//////////////////////////////////
                            if (ToolUtil.isNotEmpty(redisMessage)) {

                                if (redisMessage.equals(sendMsg)) {//接收到了消息

                                    stockMessage = stockMessage + "," + forOrderBuy.getOrderBuyPosition() + ",1," + forOrderBuy.getOrderBuyCaseId();

                                    forOrderBuy.setOrderBuyState(1);//已出货

                                    System.out.println("验证消息成功");

                                    redisTemplate.delete(redisKey);
                                    logger.error("删除缓存值:"+ redisMessage + "\n" + redisMessageSuccess);
                                    break A;
                                }
                            }
                        }
                        //如果循环完次数后还是没有收到应答消息，该货道的一个商品出货失败
                        //一般方法不会执行到8次
                        if (j == 7) {//循环到最后一次
                            forOrderBuy.setOrderBuyState(2);//出货失败
                        }
                    }
                    //最后统一修改信息
                    forOrderBuy.setOrderBuyRefund(0);//未退款
                    this.orderBuyMapper.updateByPrimaryKeySelective(forOrderBuy);
                }
                //发送完所有消息后添加订单失败统计，修改订单状态
                OnlineOrder onlineOrder = new OnlineOrder();
                onlineOrder.setOnlineOrderId(onlineOrderId);
                OnlineOrder selectOnlineOrder = this.onlineOrderMapper.selectByPrimaryKeySelective(onlineOrder);
                //根据订单id查询商品信息
                List<OrderBuy> orderBuyList = this.orderBuyMapper.selectByExampleSelective(orderBuy);
                if (ToolUtil.isNotEmpty(orderBuyList)) {
                    Integer allCount = orderBuyList.size();//所有购买的商品数量
                    Integer failCount = 0;//出货失败的商品数量
                    Integer successCount = 0;//出货成功的数量
                    Double failMoney = 0.00;//出货失败金额
                    for (OrderBuy forOrderBuy: orderBuyList) {
                        if (forOrderBuy.getOrderBuyState() == 2) {
                            //出货失败记录数量
                            failCount += 1;
                            failMoney = BigDecimalUtils.add(failMoney, forOrderBuy.getOrderBuyGoodsPrice());//单价
                        }else if (forOrderBuy.getOrderBuyState() == 1) {
                            //出货成功记录数量
                            successCount += 1;
                        }
                    }
                    //判断订单状态
                    if (failCount == allCount) {
                        //如果购买的数量等于失败的数量，就是全部失败
                        onlineOrder.setOnlineOrderShipment(3);//全部失败
                    }else if (successCount == allCount) {
                        //如果购买的数量等于成功的数量，就是全部成功
                        onlineOrder.setOnlineOrderShipment(1);//全部成功
                    }else {
                        onlineOrder.setOnlineOrderShipment(2);//出货异常
                    }
                    this.onlineOrderMapper.updateByPrimaryKeySelective(onlineOrder);

                    if (successCount != allCount) {
                        //如果不是全部成功，就是失败,添加订单失败记录
                        OrderFail orderFail = new OrderFail();
                        orderFail.setOrderFailMoney(failMoney);
                        orderFail.setOrderFailOrderId(onlineOrderId);
                        orderFail.setOrderFailReason(0);
                        Equipment equipment = new Equipment();
                        equipment.setEquipmentId(trailsMs[0]);
                        Equipment selectEquipment = this.equipmentMapper.selectByPrimary(equipment);
                        if (ToolUtil.isNotEmpty(selectEquipment)) {
                            orderFail.setOrderFailEquipmentSignal(selectEquipment.getEquipmentSignal());
                        }
                        String type = null;
                        if (selectOnlineOrder.getOnlineOrderType().equals("1")){
                            type = "微信";
                        }else if (selectOnlineOrder.getOnlineOrderType().equals("2")) {
                            type = "支付宝";
                        }
                        orderFail.setOrderFailUserId(selectOnlineOrder.getOnlineOrderUserId());
                        orderFail.setOrderFailCustomerId(selectOnlineOrder.getOnlineOrderOpenid());
                        this.orderFailMapper.insertSelective(orderFail);
                        //推送订单失败
                        User user = new User();
                        user.setUserId(selectOnlineOrder.getOnlineOrderUserId());
                        User selectUser = this.userMapper.selectByPrimaryKey(user);
                        if (ToolUtil.isNotEmpty(selectUser)) {
                            //推送给商户有订单失败
                            String message = "订单出货失败:\n设备ID:%s\n订单编号:%s\n支付方式:%s\n出货异常的商品总金额:%s";
                            PushUtils.getInstance().pushMessage(selectUser.getUserAccount(), String.format(message, selectEquipment.getEquipmentId(),
                                    selectOnlineOrder.getOnlineOrderDealNumber(), type, failMoney));
                        }
                    }
                }
                //库存推送
                RunnerShipment runnerShipment = new RunnerShipment();
                runnerShipment.stock(stockMessage.split(","),onlineOrderId);

            }else if (theme.equals("SetUse")) {//设备停用/开启指令


                B:for (int j = 0; j < 8; j++) {

                    //发送指令
                    PubMsg.publish(message, "SetUse/" + trailsMs[0]);
                    logger.error("发送mqtt消息: 主题:("+theme+") 消息:("+message+") 第" + (j+1) + "次");

                    for (int getMsg = 0; getMsg < 5; getMsg++) {
                        Thread.sleep(1000);
                        //获取缓存数据
                        redisMessage = redisTemplate.boundValueOps(redisKey).get();
                        logger.error("接收缓存的消息:" + redisMessage);

                        if (null != redisMessage) {

                            String[] msg = redisMessage.split(",");
                            if (trailsMs[0].equals(msg[0]) && msg[1].equals(trailsMs[1]) && msg[2].equals("OK")) {//接收到了消息

                                //更改设备状态
                                Equipment equipment = new Equipment();
                                if (trailsMs[2].equals("usable")) {
                                    equipment.setEquipmentUseCondition(0);//可用
                                }else if (trailsMs[2].equals("unusable")) {
                                    equipment.setEquipmentUseCondition(1);//不可用
                                }
                                equipment.setEquipmentId(trailsMs[0]);
                                this.equipmentMapper.updateByPrimaryKeySelective(equipment);

                                System.out.println("验证消息成功");

                                redisTemplate.delete(redisKey);
                                logger.error("删除缓存值:"+ redisMessage);
                                break B;
                            }
                        }
                    }
                }
            }else if (theme.equals("RefreshGoods")) {

                C:for (int j = 0; j < 8; j++) {

                    //发送指令
                    PubMsg.publish(message, "RefreshGoods/" + trailsMs[0]);
                    logger.error("发送mqtt消息: 主题:("+theme+") 消息:("+message+") 第" + (j+1) + "次");

                    for (int getMsg = 0; getMsg < 5; getMsg++) {
                        Thread.sleep(1000);
                        //获取缓存数据
                        redisMessage = redisTemplate.boundValueOps(redisKey).get();
                        logger.error("接收缓存的消息:" + redisMessage);

                        if (null != redisMessage) {

                            String[] msg = redisMessage.split(",");
                            if (trailsMs[0].equals(msg[0]) && msg[1].equals(trailsMs[1])) {//接收到了消息

                                System.out.println("验证消息成功");

                                redisTemplate.delete(redisKey);
                                logger.error("删除缓存值:"+ redisMessage);
                                break C;
                            }
                        }
                    }
                }
            }else if (theme.equals("ChangeBanner")) {
                D:for (int j = 0; j < 8; j++) {

                    //发送指令
                    PubMsg.publish(message, "ChangeBanner/" + trailsMs[0]);
                    logger.error("发送mqtt消息: 主题:("+theme+") 消息:("+message+") 第" + (j+1) + "次");

                    for (int getMsg = 0; getMsg < 5; getMsg++) {
                        Thread.sleep(1000);
                        //获取缓存数据
                        redisMessage = redisTemplate.boundValueOps(redisKey).get();
                        logger.error("接收缓存的消息:" + redisMessage);

                        if (null != redisMessage) {

                            String[] msg = redisMessage.split(",");
                            if (trailsMs[0].equals(msg[0]) && msg[1].equals(trailsMs[1]) && msg[2].equals("OK")) {//接收到了消息

                                System.out.println("验证消息成功");

                                redisTemplate.delete(redisKey);
                                logger.error("删除缓存值:"+ redisMessage);
                                break D;
                            }
                        }
                    }
                }
            }else if (theme.equals("TestMouth")) {
                //货到测试主题
                A:for (Trails trails:trailsList) {

                    String fourNumber = ToolUtil.getRandom();//随机数(每次出商品应答失败后不能更换随机数)
                    //E:for (int j = 0; j < 8; j++) {

                        String trailsType = "";
                        String shipmentNumber = "1";
                        //查询货道类型
                        Dict dict = new Dict();
                        dict.setId(trails.getTrailsType());
                        Dict selectDice = this.dictMapper.selectByPrimaryKeySelective(dict);

                        if (selectDice.getNum() == 1) {
                            trailsType = "A";//弹簧
                        }else if (selectDice.getNum() == 3) {
                            trailsType = "B";//电子锁
                        }else if (selectDice.getNum() == 2) {
                            trailsType = "C";//履带
                            shipmentNumber = trails.getTrailsTrackTime().toString();
                        }

                        //发送指令
                        String sendMsg = trailsMs[0]+","+fourNumber+","+trails.getTrailsPosition()+","+shipmentNumber+","+trailsType+","+trails.getTrailsCaseId();
                        PubMsg.publish(sendMsg, "TestMouth/" + trailsMs[0]);
                        logger.error("发送mqtt消息: 主题:("+theme+") 消息:("+sendMsg+") 第" + (1) + "次");

                        for (int getMsg = 0; getMsg < 20; getMsg++) {
                            Thread.sleep(1000);

                            //获取缓存数据
                            redisMessage = redisTemplate.boundValueOps(redisKey).get();
                            logger.error("接收缓存的消息:" + redisMessage);

                            if (null != redisMessage) {

                                if (redisMessage.equals(sendMsg)) {//接收到了消息

                                    /////////////////////////////////接收测试结果主题////////////////////////////////
                                    for (int i = 0; i < 20; i++) {
                                        Thread.sleep(1000);

                                        //////////////////////////////接收到测试结果主题//////////////////////////////////
                                        String TestResult = redisTemplate.boundValueOps("TestResult-" + trailsMs[0]).get();
                                        if (ToolUtil.isNotEmpty(TestResult)) {
                                            String[] testResult = TestResult.split(",");
                                            if (testResult[0].equals(trailsMs[0]) && testResult[2].equals(trails.getTrailsPosition())) {
                                                //if (testResult[3].equals("0")) {
                                                    redisTemplate.delete("TestResult-" + trailsMs[0]);

                                                    System.out.println("验证消息成功");

                                                    redisTemplate.delete(redisKey);
                                                    logger.error("删除缓存值:"+ redisMessage);
//                                                break E;
                                                    continue A;
                                                //}

                                            }
                                        }
                                    }
                                    continue A;
                                }
                            }
                        }
                    //}
                }
            }

        } catch (Exception e) {
            logger.error("发送mqtt消息异常");
            logger.error(e);
            e.printStackTrace();
        }

    }

    public void start() {
        logger.error("开始： " + threadName);
        if (thread == null) {
            thread = new Thread(this, threadName);
            thread.start();
        }
    }


    public RedisTemplate<String, String> getRedisTemplate() {
        return redisTemplate;
    }

    public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public Thread getThread() {
        return thread;
    }

    public void setThread(Thread thread) {
        this.thread = thread;
    }

    public String getThreadName() {
        return threadName;
    }

    public void setThreadName(String threadName) {
        this.threadName = threadName;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getTheme() {
        return theme;
    }

    public void setTheme(String theme) {
        this.theme = theme;
    }

    public String getRedisKey() {
        return redisKey;
    }

    public void setRedisKey(String redisKey) {
        this.redisKey = redisKey;
    }

    public Integer getOnlineOrderId() {
        return onlineOrderId;
    }

    public void setOnlineOrderId(Integer onlineOrderId) {
        this.onlineOrderId = onlineOrderId;
    }

    public List<Trails> getTrailsList() {
        return trailsList;
    }

    public void setTrailsList(List<Trails> trailsList) {
        this.trailsList = trailsList;
    }
}
